package org.xenei.jdbc4sparql.sparql.parser.jsqlparser.functions;
import java.sql.SQLException;
import java.util.Arrays;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import org.xenei.jdbc4sparql.iface.name.ColumnName;
import org.xenei.jdbc4sparql.sparql.SparqlQueryBuilder;
import org.xenei.jdbc4sparql.sparql.parser.jsqlparser.SparqlExprVisitor.AliasInfo;
import org.xenei.jdbc4sparql.sparql.parser.jsqlparser.proxies.ExprInfoFactory;
import com.hp.hpl.jena.sparql.expr.E_StrLength;
import com.hp.hpl.jena.sparql.expr.E_StrLowerCase;
import com.hp.hpl.jena.sparql.expr.E_StrReplace;
import com.hp.hpl.jena.sparql.expr.E_StrSubstring;
import com.hp.hpl.jena.sparql.expr.E_StrUpperCase;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.nodevalue.NodeValueString;
public class StringFunctionHandler extends AbstractFunctionHandler {
public static final String[] STRING_FUNCTIONS = {
"LENGTH", "SUBSTRING", "UCASE", "LCASE", "REPLACE"
};
private static final int LENGTH = 0;
private static final int SUBSTRING = 1;
private static final int UCASE = 2;
private static final int LCASE = 3;
private static final int REPLACE = 4;
public StringFunctionHandler(final SparqlQueryBuilder builder) {
super(builder);
}
private String escapeRegex(final NodeValueString pattern) {
final String chars = "\\.^$*+?()[{|";
final StringBuilder sb = new StringBuilder();
for (final char c : pattern.asUnquotedString().toCharArray()) {
if (chars.indexOf(c) > -1) {
sb.append("\\");
}
sb.append(c);
}
return sb.toString();
}
@Override
public Expr handle(final Function func, final AliasInfo alias)
throws SQLException {
int i = Arrays.asList(StringFunctionHandler.STRING_FUNCTIONS).indexOf(
func.getName().toUpperCase());
if (i == -1) {
final String s = func.getName().toUpperCase();
if ("LEN".equals(s)) {
i = StringFunctionHandler.LENGTH;
}
else if ("UPPER".equals(s)) {
i = StringFunctionHandler.UCASE;
}
else if ("LOWER".equals(s)) {
i = StringFunctionHandler.LCASE;
}
}
switch (i) {
case LENGTH:
return handleExpr1(E_StrLength.class, func,
java.sql.Types.VARCHAR, alias);
case SUBSTRING:
return handleSubString(func, alias);
case UCASE:
return handleExpr1(E_StrUpperCase.class, func,
java.sql.Types.VARCHAR, alias);
case LCASE:
return handleExpr1(E_StrLowerCase.class, func,
java.sql.Types.VARCHAR, alias);
case REPLACE:
return handleReplace(func, alias);
default:
return null;
}
}
protected Expr handleReplace(final Function func, final AliasInfo alias)
throws SQLException {
final ExpressionList l = func.getParameters();
if (l == null) {
throw getNoArgumentEx(func, "three");
}
if (l.getExpressions().size() != 3) {
throw getToManyArgumentEx(func, "three");
}
// third param
((Expression) l.getExpressions().get(2)).accept(exprVisitor);
Expr arg3 = exprVisitor.getResult();
if (arg3 instanceof NodeValueString) {
arg3 = new NodeValueString(escapeRegex((NodeValueString) arg3));
}
else {
throw new IllegalArgumentException("parameter 3 must be a string");
}
// second param
((Expression) l.getExpressions().get(1)).accept(exprVisitor);
Expr arg2 = exprVisitor.getResult();
if (arg2 instanceof NodeValueString) {
arg2 = new NodeValueString(escapeRegex((NodeValueString) arg2));
}
else {
throw new IllegalArgumentException("parameter 2 must be a string");
}
// first param
((Expression) l.getExpressions().get(0)).accept(exprVisitor);
final Expr arg1 = exprVisitor.getResult();
final Expr expr = new E_StrReplace(arg1, arg2, arg3, null);
// final ColumnName colName = tblName.getColumnName(func.getName());
final ColumnName colName = tblName.getColumnName(alias.getAlias());
builder.registerFunction(colName, java.sql.Types.VARCHAR);
return ExprInfoFactory.getInstance(expr, exprVisitor.getColumns(),
colName);
}
protected Expr handleSubString(final Function func, final AliasInfo alias)
throws SQLException {
final ExpressionList l = func.getParameters();
Expr expr3 = null;
Expr expr2 = null;
Expr expr1 = null;
if (l == null) {
throw getNoArgumentEx(func, "two or three");
}
final int count = l.getExpressions().size();
if (count < 2) {
throw this.getWrongArgumentCountEx(func, "two or three", count);
}
if (count > 3) {
throw getToManyArgumentEx(func, "two or three");
}
// push expressions in reverse order.
// third param
if (count == 3) {
((Expression) l.getExpressions().get(2)).accept(exprVisitor);
expr3 = exprVisitor.getResult();
}
// second param
((Expression) l.getExpressions().get(1)).accept(exprVisitor);
expr2 = exprVisitor.getResult();
// first param
((Expression) l.getExpressions().get(0)).accept(exprVisitor);
expr1 = exprVisitor.getResult();
final Expr expr = new E_StrSubstring(expr1, expr2, expr3);
// final ColumnName colName = tblName.getColumnName(func.getName());
final ColumnName colName = tblName.getColumnName(alias.getAlias());
builder.registerFunction(colName, java.sql.Types.VARCHAR);
return ExprInfoFactory.getInstance(expr, exprVisitor.getColumns(),
colName);
}
}